package main;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Observable;
import java.util.Observer;

public class Main implements Observer{
	private PageRetriever myPR;
	private PageParser myPP;
	private UserInterface myUI;
	private PageAnalyzer myPA;
	
	public Main(final List<String> keywords, final int numPages, final String seedURL) throws MalformedURLException {
		System.out.println("I'm in the constructor");
		myPR = new PageRetriever();
		myPP = new PageParser();
		myPA = new PageAnalyzer();
		
		myPR.addObserver(this);
		myPP.addObserver(this);
		myPA.addObserver(this);
		
		myPR.addPage(new String(seedURL));
		myPR.getNextPage();
	}
	
	public Main() {
		//Initialize classes
		myUI = new UserInterface();
		myPR = new PageRetriever();
		myPP = new PageParser();
		myPA = new PageAnalyzer();
		
		//set up observers
		myUI.addObserver(this);
		myPR.addObserver(this);
		myPP.addObserver(this);
		myPA.addObserver(this);
		
		//start the UI
		myUI.startUI();	
	}
	
	@Override
	public void update(Observable o, Object arg) {
//		System.out.println("I'm updating");
		if (o.getClass().equals(myPR.getClass())) {
//			System.out.println("I'm in the Main update method from the PR");
			if (arg.equals("DONE")) {
				myPA.tabulateStatistics();
			} else {
				try {
					handlePR((Page)arg);
				} catch (MalformedURLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		} else if (o.getClass().equals(myPP.getClass())) {
//			System.out.println("I'm in the main update method from the PP!");
			handlePP((Page)arg);
			//TODO: need a way to tell everyone that the list is empty!!!
		} else if (o.getClass().equals(myPA.getClass())) {
//			System.out.println("I'm in the main update method from the PA!");
			handlePA((StatisticsContainer)arg);
		} else if (o.getClass().equals(myUI.getClass())) { //something is up with this...
//			System.out.println("I'm in the Main update method from the UI!");
			try {
				handleUI((StartUpContainer)arg);
			} catch (MalformedURLException e) {
				e.printStackTrace();
			}
		}
	}
	
	private void handlePR(Page thePage) throws MalformedURLException {
//		System.out.println("I'm in the Main handlePR method");
		myPP.parsePage(thePage);
	}
	
	private void handleUI(final StartUpContainer theSUC) throws MalformedURLException {
		//send seed URL to PR
//		System.out.println("I'm in the Main handleUI method");
		myPR.setUp(theSUC.getNumPages());
		myPP.setUp(theSUC.getNumPages());
		myPA.setUp(theSUC.getKeywords(), theSUC.getNumPages());
		
		if (myPR.addPage(new String(theSUC.getSeedURL().toString())) == true) {
			myPR.getNextPage();
		}

		//TODO - send numPages to PR and PA
	}
	
	private void handlePP(final Page thePage) {
//		System.out.println("I'm in the Main handlePP method");
		myPA.analyzePage(thePage);
		if (myPA.getPagesAnalyzed() <= myPA.getMaxPages()) {
			for (URL link : thePage.getLinks()) {
				System.out.println("link from pp: " + link.toString());
				myPR.addPage(link.toString());
			}
			while (myPR.queueNotEmpty() == true) {
				myPR.getNextPage();
			}
		}
		//Flow of control - within the while loop above,
		//a bunch of calls to PR and PP get placed on the stack
		//until both queues are empty
		//Then everything pops off the call stack and this next line of code is executed
		//within each handlePP call on the stack
		//Basically -- all analyzations happen at the end in reverse order of retrieve/parse
		//TODO: need some way to break out of that while loop if max pages		
	}
	
	private void handlePA(final StatisticsContainer theSC) {
		myUI.statsUI(theSC);
	}
	
	public static void main(final String[] args) throws MalformedURLException {
//		System.out.println("I'm in Main");
//		List<String> keywords = new ArrayList<String>();
//		keywords.add("advanced");
//		Main myMain = new Main(keywords, 20, "http://css.insttech.washington.edu/~mealden/");
		System.out.println("Testing commit");
		new Main();
	}
}



